﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;

public class FaceAssociateCtrl : MonoBehaviour
{
    ///枚举类：编辑类型
    public enum EditType 
    {
        positionX = 1,
        positionY,
        positionZ,
        positionXReverse,
        positionYReverse,
        positionZReverse,
        scaleX,
        scaleY,
        scaleZ,
        rotationX,
        rotationY,
        rotationZ,
        rotationXReverse,
        rotationYReverse,
        rotationZReverse
    }

    struct TransformData
    {
        public Vector3 localPosition;
        public Vector3 localEulerAngles;
        public Vector3 localScale;
    }

    struct ObjectCtrl
    {
        public int rate;
        public List<GameObject> objs;
        public List<EditType> types;
    }

    #region 控制属性
    
    [Header("额头内外")] 
    public int browWidthRate;
    [Range(-1, 1)] public float browWidthValue;
    private float browWidthValueTmp;
    public List<GameObject> browWidthObjects;
    public List<EditType> browWidthTypes;
    
    [Header("额头上下")] 
    public int browUpDownRate;
    [Range(-1, 1)] public float browUpDownValue;
    private float browUpDownValueTmp;
    public List<GameObject> browUpDownObjects;
    public List<EditType> browUpDownTypes;
    
    [Space] //-------------------------------------
    
    [Header("眉骨内外")] 
    public int eyebrowInOutRate;
    [Range(-1, 1)] public float eyebrowInOutValue;
    private float eyebrowInOutValueTmp;
    public List<GameObject> eyebrowInOutObjects;
    public List<EditType> eyebrowInOutTypes;
    
    [Header("眉骨上下")]
    public int eyebrowUpDownRate;
    [Range(-1, 1)] public float eyebrowUpDownValue;
    private float eyebrowUpDownValueTmp;
    public List<GameObject> eyebrowUpDownObjects;
    public List<EditType> eyebrowUpDownTypes;

    [Space] //-----------------------------------------
    
    [Header("眼睛大小")] 
    public int eyeSizeRate;
    [Range(-1, 1)] public float eyeSizeValue;
    private float eyeSizeValueTmp;
    public List<GameObject> eyeSizeObjects;
    public List<EditType> eyeSizeTypes;
    
    [Header("眼睛上下")] 
    public int eyeUpDownRate;
    [Range(-1, 1)] public float eyeUpDownValue;
    private float eyeUpDownValueTmp;
    public List<GameObject> eyeUpDownObjects;
    public List<EditType> eyeUpDownTypes;
    
    [Header("眼睛宽窄")] 
    public int eyeWidthRate;
    [Range(-1, 1)] public float eyeWidthValue;
    private float eyeWidthValueTmp;
    public List<GameObject> eyeWidthObjects;
    public List<EditType> eyeWidthTypes;

    [Space] //-----------------------------------------

    [Header("鼻子长短")] 
    public int noseShortLongRate;
    [Range(-1, 1)] public float noseShortLongValue;
    private float noseShortLongValueTmp;
    public List<GameObject> noseShortLongObjects;
    public List<EditType> noseShortLongTypes;
    
    [Header("鼻梁高低")] 
    public int noseUpDwonRate;
    [Range(-1, 1)] public float noseUpDwonValue;
    private float noseUpDwonValueTmp;
    public List<GameObject> noseUpDwonObjects;
    public List<EditType> noseUpDwonTypes;
    
    [Header("鼻头上下")] 
    public int nosepointUpDownRate;
    [Range(-1, 1)] public float nosepointUpDownValue;
    private float nosepointUpDownValueTmp;
    public List<GameObject> nosepointUpDownObjects;
    public List<EditType> nosepointUpDownTypes;
    
    [Header("鼻头左右")] 
    public int nosepointLeftRightRate;
    [Range(-1, 1)] public float nosepointLeftRightValue;
    private float nosepointLeftRightValueTmp;
    public List<GameObject> nosepointLeftRightObjects;
    public List<EditType> nosepointLeftRightTypes;
    
    [Header("鼻头宽窄")] 
    public int nosepointWidthRate;
    [Range(-1, 1)] public float nosepointWidthValue;
    private float nosepointWidthValueTmp;
    public List<GameObject> nosepointWidthObjects;
    public List<EditType> nosepointWidthTypes;
    
    [Space] //-----------------------------------------
    
    [Header("嘴唇上下")] 
    public int mouthUpDownRate;
    [Range(-1, 1)] public float mouthUpDownValue;
    private float mouthUpDownValueTmp;
    public List<GameObject> mouthUpDownObjects;
    public List<EditType> mouthUpDownTypes;
    
    [Header("嘴唇前后")] 
    public int mouthFrontBackRate;
    [Range(-1, 1)] public float mouthFrontBackValue;
    private float mouthFrontBackValueTmp;
    public List<GameObject> mouthFrontBackObjects;
    public List<EditType> mouthFrontBackTypes;
    
    [Header("嘴唇大小")] 
    public int mouthSizeRate;
    [Range(-1, 1)] public float mouthSizeValue;
    private float mouthSizeValueTmp;
    public List<GameObject> mouthSizeObjects;
    public List<EditType> mouthSizeTypes;
    
    [Header("嘴唇薄厚")] 
    public int mouthThicknessRate;
    [Range(-1, 1)] public float mouthThicknessValue;
    private float mouthThicknessValueTmp;
    public List<GameObject> mouthThicknessObjects;
    public List<EditType> mouthThicknessTypes;
    
    //[Space] //-----------------------------------------  
    
    [Header("颧骨内外")] 
    public int chopsInOutRate;
    [Range(-1, 1)] public float chopsInOutValue;
    private float chopsInOutValueTmp;
    public List<GameObject> chopsInOutObjects;
    public List<EditType> chopsInOutTypes;
    
    [Header("颧骨上下")] 
    public int chopsUpDwonRate;
    [Range(-1, 1)] public float chopsUpDwonValue;
    private float chopsUpDwonValueTmp;
    public List<GameObject> chopsUpDwonObjects;
    public List<EditType> chopsUpDwonTypes;
    
    [Space] //--------------------------------------

    [Header("脸颊胖瘦")] 
    public int cheekInOutRate;
    [Range(-1, 1)] public float cheekInOutValue;
    private float cheekInOutValueTmp;
    public List<GameObject> cheekInOutObjects;
    public List<EditType> cheekInOutTypes;
    
    [Space] //--------------------------------------

    [Header("下颌角高低")] 
    public int jawconerInOutRate;
    [Range(-1, 1)] public float jawconerInOutValue;
    private float jawconerInOutValueTmp;
    public List<GameObject> jawconerInOutObjects;
    public List<EditType> jawconerInOutTypes;
    
    [Header("下颌角宽窄")] 
    public int jawconerWidthRate;
    [Range(-1, 1)] public float jawconerWidthValue;
    private float jawconerWidthValueTmp;
    public List<GameObject> jawconerWidthObjects;
    public List<EditType> jawconerWidthTypes;
    
    [Space] //--------------------------------------

    [Header("下颌骨上下")] 
    public int jawUpDownRate;
    [Range(-1, 1)] public float jawUpDownValue;
    private float jawUpDownValueTmp;
    public List<GameObject> jawUpDownObjects;
    public List<EditType> jawUpDownTypes;
    
    [Header("下颌骨内外")] 
    public int jawInOutRate;
    [Range(-1, 1)] public float jawInOutValue;
    private float jawInOutValueTmp;
    public List<GameObject> jawInOutObjects;
    public List<EditType> jawInOutTypes;
    
    [Header("下颌骨旋转")] 
    public int jawRotationRate;
    [Range(-1, 1)] public float jawRotationValue;
    private float jawRotationValueTmp;
    public List<GameObject> jawRotationObjects;
    public List<EditType> jawRotationTypes;
    
    [Space] //--------------------------------------

    [Header("下巴高低")] 
    public int chinInOutRate;
    [Range(-1, 1)] public float chinInOutValue;
    private float chinInOutValueTmp;
    public List<GameObject> chinInOutObjects;
    public List<EditType> chinInOutTypes;
    
    [Header("下巴长短")] 
    public int chinShortLongRate;
    [Range(-1, 1)] public float chinShortLongValue;
    private float chinShortLongValueTmp;
    public List<GameObject> chinShortLongObjects;
    public List<EditType> chinShortLongTypes;
    
    [Header("下巴宽窄")] 
    public int chinWidthRate;
    [Range(-1, 1)] public float chinWidthValue;
    private float chinWidthValueTmp;
    public List<GameObject> chinWidthObjects;
    public List<EditType> chinWidthTypes;
    
    #endregion
    
    [Space(20)]
    
    public GameObject rootObject;
    private Dictionary<string, TransformData> childrenTransfroms = new Dictionary<string, TransformData>();
    private Dictionary<string, ObjectCtrl> ctrlObjs = new Dictionary<string, ObjectCtrl>();

    private bool m_isInited = false;

    #region 本地配置
    private string jsonPath = "Assets/Arts/Character/Role/Player/roleOriginalData_{0}.json";
    private string objName = "";
    InputData _inputDate = new InputData ();
    InputData inputDate 
    {
        get { return _inputDate; }
        set { _inputDate = value; }
    }
    
    InputData LoadFromFile(string path)
    {
        if (!File.Exists (path))
            return null;
        StreamReader sr = new StreamReader (path);

        if (sr == null)
            return null;

        string json = sr.ReadToEnd ();
        if (json.Length > 0)
            return JsonUtility.FromJson<InputData> (json);
        return null;
    }
    
    public void ImportOriginalData()
    {
#if UNITY_EDITOR
        Debug.Log("============ ImportOriginalData Start ==============");
        
        if (LoadFromFile(jsonPath) != null)
            inputDate = LoadFromFile(jsonPath);
        
        childrenTransfroms.Clear();

        var list = inputDate.data;
        for (int i = 0; i < list.Length; i++)
        {
            var data = list[i];
            TransformData trans = new TransformData();
            trans.localPosition = data.localPosition;
            trans.localScale = data.localScale;
            trans.localEulerAngles = data.localEulerAngles;
            childrenTransfroms.Add(data.name, trans);
        }

        ResetTransforms();
        ResetAllValues();
        
        Debug.Log("============ ImportOriginalData End ==============");
#endif
    }

    public void ExportOriginalData()
    {
#if UNITY_EDITOR
        Debug.Log("============ ExportOriginalData Start ==============");
        List<ObjectTransformData> list = new List<ObjectTransformData>();
        var allChild = rootObject.transform.GetComponentsInChildren<Transform>();
        foreach (Transform child in allChild)
        {
            ObjectTransformData data = new ObjectTransformData();
            data.name = child.name;
            data.localPosition = child.localPosition;
            data.localScale = child.localScale;
            data.localEulerAngles = child.localEulerAngles;
            list.Add(data);
        }

        inputDate.data = list.ToArray();
        
        string json = JsonUtility.ToJson (inputDate, true);
        Debug.Log("==== ExportOriginalData : json = "+json);
        File.WriteAllText (jsonPath, json, Encoding.UTF8);
        Debug.Log("============ ExportOriginalData End ==============");
#endif
    }
    
    #endregion
    
    #region 初始化

    void Awake()
    {
        if (m_isInited) return;
        
        InitCtrlObjects();
        childrenTransfroms.Clear();
        m_isInited = true;
    }

    /// <summary>
    /// 初始化
    /// </summary>
    public void OnInit()
    {
        if (m_isInited) return;
        
        objName = gameObject.transform.parent.name;
        jsonPath = string.Format(jsonPath, objName);
        ResetTempArguments();
        childrenTransfroms.Clear();
        m_isInited = true;
    }

    /// <summary>
    /// 初始化所有控制对象
    /// </summary>
    public void InitCtrlObjects()
    {
        ObjectCtrl browWidth;
        browWidth.rate = browWidthRate;
        browWidth.objs = browWidthObjects;
        browWidth.types = browWidthTypes;
        ctrlObjs.Add("browWidth", browWidth);
        
        ObjectCtrl browUpDown;
        browUpDown.rate = browUpDownRate;
        browUpDown.objs = browUpDownObjects;
        browUpDown.types = browUpDownTypes;
        ctrlObjs.Add("browUpDown", browUpDown);
        
        ObjectCtrl eyebrowInOut;
        eyebrowInOut.rate = eyebrowInOutRate;
        eyebrowInOut.objs = eyebrowInOutObjects;
        eyebrowInOut.types = eyebrowInOutTypes;
        ctrlObjs.Add("eyebrowInOut", eyebrowInOut);
        
        ObjectCtrl eyebrowUpDown;
        eyebrowUpDown.rate = eyebrowUpDownRate;
        eyebrowUpDown.objs = eyebrowUpDownObjects;
        eyebrowUpDown.types = eyebrowUpDownTypes;
        ctrlObjs.Add("eyebrowUpDown", eyebrowUpDown);
        
        ObjectCtrl eyeSize;
        eyeSize.rate = eyeSizeRate;
        eyeSize.objs = eyeSizeObjects;
        eyeSize.types = eyeSizeTypes;
        ctrlObjs.Add("eyeSize", eyeSize);

        ObjectCtrl eyeUpDown;
        eyeUpDown.rate = eyeUpDownRate;
        eyeUpDown.objs = eyeUpDownObjects;
        eyeUpDown.types = eyeUpDownTypes;
        ctrlObjs.Add("eyeUpDown", eyeUpDown);

        ObjectCtrl eyeWidth;
        eyeWidth.rate = eyeWidthRate;
        eyeWidth.objs = eyeWidthObjects;
        eyeWidth.types = eyeWidthTypes;
        ctrlObjs.Add("eyeWidth", eyeWidth);

        ObjectCtrl noseShortLong;
        noseShortLong.rate = noseShortLongRate;
        noseShortLong.objs = noseShortLongObjects;
        noseShortLong.types = noseShortLongTypes;
        ctrlObjs.Add("noseShortLong", noseShortLong);

        ObjectCtrl noseUpDwon;
        noseUpDwon.rate = noseUpDwonRate;
        noseUpDwon.objs = noseUpDwonObjects;
        noseUpDwon.types = noseUpDwonTypes;
        ctrlObjs.Add("noseUpDwon", noseUpDwon);

        ObjectCtrl nosepointUpDown;
        nosepointUpDown.rate = nosepointUpDownRate;
        nosepointUpDown.objs = nosepointUpDownObjects;
        nosepointUpDown.types = nosepointUpDownTypes;
        ctrlObjs.Add("nosepointUpDown", nosepointUpDown);

        ObjectCtrl nosepointLeftRight;
        nosepointLeftRight.rate = nosepointLeftRightRate;
        nosepointLeftRight.objs = nosepointLeftRightObjects;
        nosepointLeftRight.types = nosepointLeftRightTypes;
        ctrlObjs.Add("nosepointLeftRight", nosepointLeftRight);

        ObjectCtrl nosepointWidth;
        nosepointWidth.rate = nosepointWidthRate;
        nosepointWidth.objs = nosepointWidthObjects;
        nosepointWidth.types = nosepointWidthTypes;
        ctrlObjs.Add("nosepointWidth", nosepointWidth);

        ObjectCtrl mouthUpDown;
        mouthUpDown.rate = mouthUpDownRate;
        mouthUpDown.objs = mouthUpDownObjects;
        mouthUpDown.types = mouthUpDownTypes;
        ctrlObjs.Add("mouthUpDown", mouthUpDown);

        ObjectCtrl mouthFrontBack;
        mouthFrontBack.rate = mouthFrontBackRate;
        mouthFrontBack.objs = mouthFrontBackObjects;
        mouthFrontBack.types = mouthFrontBackTypes;
        ctrlObjs.Add("mouthFrontBack", mouthFrontBack);

        ObjectCtrl mouthSize;
        mouthSize.rate = mouthSizeRate;
        mouthSize.objs = mouthSizeObjects;
        mouthSize.types = mouthSizeTypes;
        ctrlObjs.Add("mouthSize", mouthSize);

        ObjectCtrl mouthThickness;
        mouthThickness.rate = mouthThicknessRate;
        mouthThickness.objs = mouthThicknessObjects;
        mouthThickness.types = mouthThicknessTypes;
        ctrlObjs.Add("mouthThickness", mouthThickness);

        ObjectCtrl chopsInOut;
        chopsInOut.rate = chopsInOutRate;
        chopsInOut.objs = chopsInOutObjects;
        chopsInOut.types = chopsInOutTypes;
        ctrlObjs.Add("chopsInOut", chopsInOut);

        ObjectCtrl chopsUpDwon;
        chopsUpDwon.rate = chopsUpDwonRate;
        chopsUpDwon.objs = chopsUpDwonObjects;
        chopsUpDwon.types = chopsUpDwonTypes;
        ctrlObjs.Add("chopsUpDwon", chopsUpDwon);

        ObjectCtrl cheekInOut;
        cheekInOut.rate = cheekInOutRate;
        cheekInOut.objs = cheekInOutObjects;
        cheekInOut.types = cheekInOutTypes;
        ctrlObjs.Add("cheekInOut", cheekInOut);

        ObjectCtrl jawconerInOut;
        jawconerInOut.rate = jawconerInOutRate;
        jawconerInOut.objs = jawconerInOutObjects;
        jawconerInOut.types = jawconerInOutTypes;
        ctrlObjs.Add("jawconerInOut", jawconerInOut);

        ObjectCtrl jawconerWidth;
        jawconerWidth.rate = jawconerWidthRate;
        jawconerWidth.objs = jawconerWidthObjects;
        jawconerWidth.types = jawconerWidthTypes;
        ctrlObjs.Add("jawconerWidth", jawconerWidth);

        ObjectCtrl jawUpDown;
        jawUpDown.rate = jawUpDownRate;
        jawUpDown.objs = jawUpDownObjects;
        jawUpDown.types = jawUpDownTypes;
        ctrlObjs.Add("jawUpDown", jawUpDown);

        ObjectCtrl jawInOut;
        jawInOut.rate = jawInOutRate;
        jawInOut.objs = jawInOutObjects;
        jawInOut.types = jawInOutTypes;
        ctrlObjs.Add("jawInOut", jawInOut);

        ObjectCtrl jawRotation;
        jawRotation.rate = jawRotationRate;
        jawRotation.objs = jawRotationObjects;
        jawRotation.types = jawRotationTypes;
        ctrlObjs.Add("jawRotation", jawRotation);

        ObjectCtrl chinInOut;
        chinInOut.rate = chinInOutRate;
        chinInOut.objs = chinInOutObjects;
        chinInOut.types = chinInOutTypes;
        ctrlObjs.Add("chinInOut", chinInOut);

        ObjectCtrl chinShortLong;
        chinShortLong.rate = chinShortLongRate;
        chinShortLong.objs = chinShortLongObjects;
        chinShortLong.types = chinShortLongTypes;
        ctrlObjs.Add("chinShortLong", chinShortLong);

        ObjectCtrl chinWidth;
        chinWidth.rate = chinWidthRate;
        chinWidth.objs = chinWidthObjects;
        chinWidth.types = chinWidthTypes;
        ctrlObjs.Add("chinWidth", chinWidth);
    }

    /// <summary>
    /// 初始化基础变量
    /// </summary>
    private void ResetTempArguments()
    {
        browWidthValueTmp = browWidthValue;
        browUpDownValueTmp = browUpDownValue;
        eyebrowInOutValueTmp = eyebrowInOutValue;
        eyebrowUpDownValueTmp = eyebrowUpDownValue;
        eyeSizeValueTmp = eyeSizeValue;
        eyeUpDownValueTmp = eyeUpDownValue;
        eyeWidthValueTmp = eyeWidthValue;
        noseShortLongValueTmp = noseShortLongValue;
        noseUpDwonValueTmp = noseUpDwonValue;
        nosepointUpDownValueTmp = nosepointUpDownValue;
        nosepointLeftRightValueTmp = nosepointLeftRightValue;
        nosepointWidthValueTmp = nosepointWidthValue;
        mouthUpDownValueTmp = mouthUpDownValue;
        mouthFrontBackValueTmp = mouthFrontBackValue;
        mouthSizeValueTmp = mouthSizeValue;
        mouthThicknessValueTmp = mouthThicknessValue;
        chopsInOutValueTmp = chopsInOutValue;
        chopsUpDwonValueTmp = chopsUpDwonValue;
        cheekInOutValueTmp = cheekInOutValue;
        jawconerInOutValueTmp = jawconerInOutValue;
        jawconerWidthValueTmp = jawconerWidthValue;
        jawUpDownValueTmp = jawUpDownValue;
        jawInOutValueTmp = jawInOutValue;
        jawRotationValueTmp = jawRotationValue;
        chinInOutValueTmp = chinInOutValue;
        chinShortLongValueTmp = chinShortLongValue;
        chinWidthValueTmp = chinWidthValue;
    }
    
    #endregion
    
    #region 重置

    public void ResetAllValues()
    {
        browWidthValueTmp = browWidthValue = 0;
        browUpDownValueTmp = browUpDownValue = 0;
        eyebrowInOutValueTmp = eyebrowInOutValue = 0;
        eyebrowUpDownValueTmp = eyebrowUpDownValue = 0;
        eyeSizeValueTmp = eyeSizeValue = 0;
        eyeUpDownValueTmp = eyeUpDownValue = 0;
        eyeWidthValueTmp = eyeWidthValue = 0;
        noseShortLongValueTmp = noseShortLongValue = 0;
        noseUpDwonValueTmp = noseUpDwonValue = 0;
        nosepointUpDownValueTmp = nosepointUpDownValue = 0;
        nosepointLeftRightValueTmp = nosepointLeftRightValue = 0;
        nosepointWidthValueTmp = nosepointWidthValue = 0;
        mouthUpDownValueTmp = mouthUpDownValue = 0;
        mouthFrontBackValueTmp = mouthFrontBackValue = 0;
        mouthSizeValueTmp = mouthSizeValue = 0;
        mouthThicknessValueTmp = mouthThicknessValue = 0;
        chopsInOutValueTmp = chopsInOutValue = 0;
        chopsUpDwonValueTmp = chopsUpDwonValue = 0;
        cheekInOutValueTmp = cheekInOutValue = 0;
        jawconerInOutValueTmp = jawconerInOutValue = 0;
        jawconerWidthValueTmp = jawconerWidthValue = 0;
        jawUpDownValueTmp = jawUpDownValue = 0;
        jawInOutValueTmp = jawInOutValue = 0;
        jawRotationValueTmp = jawRotationValue = 0;
        chinInOutValueTmp = chinInOutValue = 0;
        chinShortLongValueTmp = chinShortLongValue = 0;
        chinWidthValueTmp = chinWidthValue = 0;
    }
    
    /// <summary>
    /// 重置所有物体的Transform值
    /// </summary>
    public void ResetTransforms()
    {
        Debug.Log("OnResetClick");
        if (rootObject != null) ResetGameObject(rootObject.transform); 
    }
    
    /// <summary>
    /// 遍历目标对象，进行数值变更
    /// </summary>
    /// <param name="trans"></param>
    private void ResetGameObject(Transform trans)
    {
        foreach (Transform obj in trans) 
        {
            ResetChildTransform(obj);
            if (obj.childCount > 0) ResetGameObject(obj);
        }
    }

    /// <summary>
    /// 重置目标对象的Transform数值
    /// </summary>
    /// <param name="target"></param>
    private void ResetChildTransform(Transform target)
    {
        Debug.Log("Character ResetChild : "+target.name);
        if (childrenTransfroms.ContainsKey(target.name))
        {
            TransformData originalTransform = childrenTransfroms[target.name];
            Debug.Log(string.Format("Reset {0} original Position X = {1}", target.name, originalTransform.localPosition.x));
            target.localPosition = originalTransform.localPosition;
            target.localScale = originalTransform.localScale;
            target.localEulerAngles = originalTransform.localEulerAngles;
        }
    }
    
    #endregion
    
    #region 位置计算
    /// <summary>
    /// 更新目标对象的Transform数值
    /// </summary>
    /// <param name="target"></param>
    /// <param name="editType"></param>
    /// <param name="value"></param>
    /// <param name="rate"></param>
    private void UpdateTargetTransform(Transform target, EditType editType, float value, float rate)
    {
        if (target == null) return;
        
        //动态记录目标对象的原始数据
        TransformData originalTransform;
        if (childrenTransfroms.ContainsKey(target.name))
        {
            Debug.Log(string.Format("Character Update 111 {0}", target.name));
            originalTransform = childrenTransfroms[target.name];
        }
        else
        {
            Debug.Log(string.Format("Character Update 222 {0}", target.name));
            TransformData transData = new TransformData();
            transData.localPosition = target.localPosition;
            transData.localScale = target.localScale;
            transData.localEulerAngles = target.localEulerAngles;
            childrenTransfroms.Add(target.name, transData);
            originalTransform = transData;
        }
        
        Debug.Log(string.Format("Character Update: {0} position X = {1}", target.name, target.localPosition.x));
        
        //计算缩放值
        if (isScale(editType))
        {
            value = GetCalculateScale(value, rate);
            target.localScale = new Vector3(
                editType == EditType.scaleX ? value : target.localScale.x,
                editType == EditType.scaleY ? value : target.localScale.y,
                editType == EditType.scaleZ ? value : target.localScale.z
                );
        }
        else if (isRotation(editType))
        {
            value = GetCalculateRotation(value, rate, isReverse(editType));
            target.localEulerAngles = new Vector3(
                editType == EditType.rotationX ? 
                    originalTransform.localEulerAngles.x + value : target.localEulerAngles.x,
                editType == EditType.rotationY ? 
                    originalTransform.localEulerAngles.y + value : target.localEulerAngles.y,
                editType == EditType.rotationY ? 
                    originalTransform.localEulerAngles.z + value : target.localEulerAngles.z
            );
        }
        else //计算位置
        {
            value = GetCalculatePosition(value, rate, isReverse(editType));
            Vector3 pos = new Vector3(
                editType == EditType.positionX || editType == EditType.positionXReverse ? 
                    originalTransform.localPosition.x + value : target.localPosition.x,
                editType == EditType.positionY || editType == EditType.positionYReverse ? 
                    originalTransform.localPosition.y + value : target.localPosition.y,
                editType == EditType.positionZ || editType == EditType.positionZReverse ? 
                    originalTransform.localPosition.z + value : target.localPosition.z
                );
            target.localPosition = pos;
        }
        
        Debug.Log("Character AfterUpdate : " + target.name+", posX = "+target.transform.localPosition.x);
    }

    /// <summary>
    /// 是否为一个反置数值(-1)
    /// </summary>
    /// <param name="editType"></param>
    /// <returns></returns>
    private bool isReverse(EditType editType)
    {
        return editType == EditType.positionXReverse || editType == EditType.positionYReverse ||
               editType == EditType.positionZReverse || editType == EditType.rotationXReverse ||
               editType == EditType.rotationYReverse || editType == EditType.rotationZReverse;
    }

    private bool isRotation(EditType editType)
    {
        return editType == EditType.rotationX || editType == EditType.rotationXReverse ||
               editType == EditType.rotationY || editType == EditType.rotationYReverse ||
               editType == EditType.rotationZ || editType == EditType.rotationZReverse;
    }

    private bool isScale(EditType editType)
    {
        return editType == EditType.scaleX || editType == EditType.scaleY || editType == EditType.scaleZ;
    }

    /// <summary>
    /// 计算实际运用位置的数值
    /// </summary>
    /// <param name="value">设定的参数值(-1~1)</param>
    /// <param name="rate">设定的比例值(实际值=比例值/10000)</param>
    /// <param name="isReverse">是否反向(true表示需要*-1)</param>
    /// <returns></returns>
    private float GetCalculatePosition(float value, float rate, bool isReverse = false)
    {
        return (isReverse ? 1 : -1) * rate/10000 * value;
    }

    /// <summary>
    /// 计算缩放比例值
    /// </summary>
    /// <param name="value">设定的参数值(-1~1)，0表示缩放为1</param>
    /// <param name="rate">设定的比例值</param>
    /// <returns></returns>
    private float GetCalculateScale(float value, float rate)
    {
        return 1 + value * rate / 10000;
    }

    private float GetCalculateRotation(float value, float rate, bool isReverse = false)
    {
        return (isReverse ? 1 : -1) * rate / 10000 * value * 90;
    }
    
    #endregion
    
    /// <summary>
    /// 配置值变化响应函数，仅在Editor模式下生效
    /// </summary>
    public void OnCtrlValueChanged()
    {
        if (browWidthValueTmp != browWidthValue) {
            OnArgumentUpdate(browWidthObjects, browWidthTypes, browWidthValue, browWidthRate);
            browWidthValueTmp = browWidthValue;
        }
    
        if (browUpDownValueTmp != browUpDownValue) {
            OnArgumentUpdate(browUpDownObjects, browUpDownTypes, browUpDownValue, browUpDownRate);
            browUpDownValueTmp = browUpDownValue;
        }
    
        if (eyebrowInOutValueTmp != eyebrowInOutValue) {
            OnArgumentUpdate(eyebrowInOutObjects, eyebrowInOutTypes, eyebrowInOutValue, eyebrowInOutRate);
            eyebrowInOutValueTmp = eyebrowInOutValue;
        }
    
        if (eyebrowUpDownValueTmp != eyebrowUpDownValue) {
            OnArgumentUpdate(eyebrowUpDownObjects, eyebrowUpDownTypes, eyebrowUpDownValue, eyebrowUpDownRate);
            eyebrowUpDownValueTmp = eyebrowUpDownValue;
        }
    
        if (eyeSizeValueTmp != eyeSizeValue) {
            OnArgumentUpdate(eyeSizeObjects, eyeSizeTypes, eyeSizeValue, eyeSizeRate);
            eyeSizeValueTmp = eyeSizeValue;
        }
        
        if (eyeUpDownValueTmp != eyeUpDownValue) {
            OnArgumentUpdate(eyeUpDownObjects, eyeUpDownTypes, eyeUpDownValue, eyeUpDownRate);
            eyeUpDownValueTmp = eyeUpDownValue;
        }
        
        if (eyeWidthValueTmp != eyeWidthValue) {
            OnArgumentUpdate(eyeWidthObjects, eyeWidthTypes, eyeWidthValue, eyeWidthRate);
            eyeWidthValueTmp = eyeWidthValue;
        }

        if (noseShortLongValueTmp != noseShortLongValue) {
            OnArgumentUpdate(noseShortLongObjects, noseShortLongTypes, noseShortLongValue, noseShortLongRate);
            noseShortLongValueTmp = noseShortLongValue;
        }

        if (noseUpDwonValueTmp != noseUpDwonValue) {
            OnArgumentUpdate(noseUpDwonObjects, noseUpDwonTypes, noseUpDwonValue, noseUpDwonRate);
            noseUpDwonValueTmp = noseUpDwonValue;
        }

        if (nosepointUpDownValueTmp != nosepointUpDownValue) {
            OnArgumentUpdate(nosepointUpDownObjects, nosepointUpDownTypes, nosepointUpDownValue, nosepointUpDownRate);
            nosepointUpDownValueTmp = nosepointUpDownValue;
        }

        if (nosepointLeftRightValueTmp != nosepointLeftRightValue) {
            OnArgumentUpdate(nosepointLeftRightObjects, nosepointLeftRightTypes, nosepointLeftRightValue, nosepointLeftRightRate);
            nosepointLeftRightValueTmp = nosepointLeftRightValue;
        }

        if (nosepointWidthValueTmp != nosepointWidthValue) {
            OnArgumentUpdate(nosepointWidthObjects, nosepointWidthTypes, nosepointWidthValue, nosepointWidthRate);
            nosepointWidthValueTmp = nosepointWidthValue;
        }

        if (mouthUpDownValueTmp != mouthUpDownValue) {
            OnArgumentUpdate(mouthUpDownObjects, mouthUpDownTypes, mouthUpDownValue, mouthUpDownRate);
            mouthUpDownValueTmp = mouthUpDownValue;
        }

        if (mouthFrontBackValueTmp != mouthFrontBackValue) {
            OnArgumentUpdate(mouthFrontBackObjects, mouthFrontBackTypes, mouthFrontBackValue, mouthFrontBackRate);
            mouthFrontBackValueTmp = mouthFrontBackValue;
        }

        if (mouthSizeValueTmp != mouthSizeValue) {
            OnArgumentUpdate(mouthSizeObjects, mouthSizeTypes, mouthSizeValue, mouthSizeRate);
            mouthSizeValueTmp = mouthSizeValue;
        }

        if (mouthThicknessValueTmp != mouthThicknessValue) {
            OnArgumentUpdate(mouthThicknessObjects, mouthThicknessTypes, mouthThicknessValue, mouthThicknessRate);
            mouthThicknessValueTmp = mouthThicknessValue;
        }

        if (chopsInOutValueTmp != chopsInOutValue) {
            OnArgumentUpdate(chopsInOutObjects, chopsInOutTypes, chopsInOutValue, chopsInOutRate);
            chopsInOutValueTmp = chopsInOutValue;
        }

        if (chopsUpDwonValueTmp != chopsUpDwonValue) {
            OnArgumentUpdate(chopsUpDwonObjects, chopsUpDwonTypes, chopsUpDwonValue, chopsUpDwonRate);
            chopsUpDwonValueTmp = chopsUpDwonValue;
        }

        if (cheekInOutValueTmp != cheekInOutValue) {
            OnArgumentUpdate(cheekInOutObjects, cheekInOutTypes, cheekInOutValue, cheekInOutRate);
            cheekInOutValueTmp = cheekInOutValue;
        }

        if (jawconerInOutValueTmp != jawconerInOutValue) {
            OnArgumentUpdate(jawconerInOutObjects, jawconerInOutTypes, jawconerInOutValue, jawconerInOutRate);
            jawconerInOutValueTmp = jawconerInOutValue;
        }

        if (jawconerWidthValueTmp != jawconerWidthValue) {
            OnArgumentUpdate(jawconerWidthObjects, jawconerWidthTypes, jawconerWidthValue, jawconerWidthRate);
            jawconerWidthValueTmp = jawconerWidthValue;
        }

        if (jawUpDownValueTmp != jawUpDownValue) {
            OnArgumentUpdate(jawUpDownObjects, jawUpDownTypes, jawUpDownValue, jawUpDownRate);
            jawUpDownValueTmp = jawUpDownValue;
        }

        if (jawInOutValueTmp != jawInOutValue) {
            OnArgumentUpdate(jawInOutObjects, jawInOutTypes, jawInOutValue, jawInOutRate);
            jawInOutValueTmp = jawInOutValue;
        }

        if (jawRotationValueTmp != jawRotationValue) {
            OnArgumentUpdate(jawRotationObjects, jawRotationTypes, jawRotationValue, jawRotationRate);
            jawRotationValueTmp = jawRotationValue;
        }

        if (chinInOutValueTmp != chinInOutValue) {
            OnArgumentUpdate(chinInOutObjects, chinInOutTypes, chinInOutValue, chinInOutRate);
            chinInOutValueTmp = chinInOutValue;
        }

        if (chinShortLongValueTmp != chinShortLongValue) {
            OnArgumentUpdate(chinShortLongObjects, chinShortLongTypes, chinShortLongValue, chinShortLongRate);
            chinShortLongValueTmp = chinShortLongValue;
        }

        if (chinWidthValueTmp != chinWidthValue) {
            OnArgumentUpdate(chinWidthObjects, chinWidthTypes, chinWidthValue, chinWidthRate);
            chinWidthValueTmp = chinWidthValue;
        }

    }
    
    /// <summary>
    /// 更新对象的参数变化
    /// </summary>
    /// <param name="objs"></param>
    /// <param name="types"></param>
    /// <param name="value"></param>
    /// <param name="rate"></param>
    private void OnArgumentUpdate(List<GameObject> objs, List<EditType> types, float value, float rate)
    {
        for (int i = 0; i < objs.Count; i++)
        {
            if (objs[i] != null)
                UpdateTargetTransform(objs[i].transform, types[i], value, rate);
        }
    }

    #region Script Control
    
    public void SetCtrlObjectValue(string key, float value)
    {
        Debug.Log(string.Format("C# Character SetCtrlObjectValue, key = {0}, value = {1}", key, value));
        if (ctrlObjs.ContainsKey(key))
        {
            ObjectCtrl ctrl = ctrlObjs[key];
            OnArgumentUpdate(ctrl.objs, ctrl.types, value, ctrl.rate);
        }
    }

    #endregion
}

[Serializable]
public class InputData
{
    public ObjectTransformData[] data;
}

[Serializable]
public class ObjectTransformData
{
    public string name;
    public Vector3 localPosition;
    public Vector3 localEulerAngles;
    public Vector3 localScale;
}